Emendas Parlamentares#

Arquivos com dados em https://portaldatransparencia.gov.br/emendas

import pandas as pd
import numpy as np
import plotly.express as px
from babel.numbers import format_currency

# retirar a notação científica do pandas
# pd.set_option('display.float_format', '{:.2f}'.format)

df = pd.read_csv('../emendas.csv', sep=';')
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 2849 entries, 0 to 2848
Data columns (total 18 columns):
 #   Column                                Non-Null Count  Dtype  
---  ------                                --------------  -----  
 0   Ano                                   2849 non-null   int64  
 1   Tipo de Emenda                        2849 non-null   object 
 2   Autor da emenda                       2849 non-null   object 
 3   Número da emenda                      2849 non-null   int64  
 4   Localidade do gasto (Regionalização)  2849 non-null   object 
 5   Função                                2849 non-null   object 
 6   Subfunção                             2849 non-null   object 
 7   Programa Orçamentário                 2849 non-null   object 
 8   Ação Orçamentária                     2849 non-null   object 
 9   Plano Orçamentário                    2849 non-null   object 
 10  Código da emenda                      2849 non-null   int64  
 11  Valor empenhado                       2849 non-null   object 
 12  Valor liquidado                       2849 non-null   object 
 13  Valor pago                            2849 non-null   object 
 14  Valor Restos a Pagar Inscritos        2849 non-null   object 
 15  Valor Restos a Pagar Cancelados       2849 non-null   object 
 16  Valor Restos a Pagar Pagos            2849 non-null   object 
 17  Unnamed: 17                           0 non-null      float64
dtypes: float64(1), int64(3), object(14)
memory usage: 400.8+ KB

Estrutura#

Renomeando colunas#

# Renomeando as colunas pra trabalhar mais facilmente
df.columns = ['ano','emenda_tipo','emenda_autor','emenda_nr','local_gasto','funcao','subfuncao','orc_programa'
              ,'orc_acao','orc_plano','emenda_cod','vlr_empenhado','vlr_liquido','vlr_pago','vlr_restos_pagar_inscrito'
              ,'vlr_restos_pagar_cancelados','vlr_restos_pagar_pagos','outro']
df.head()
ano emenda_tipo emenda_autor emenda_nr local_gasto funcao subfuncao orc_programa orc_acao orc_plano emenda_cod vlr_empenhado vlr_liquido vlr_pago vlr_restos_pagar_inscrito vlr_restos_pagar_cancelados vlr_restos_pagar_pagos outro
0 2022 Emenda Individual - Transferências Especiais MARCIO ALVINO 6 SÃO PAULO (UF) Encargos especiais Outras transferências 0903 - OPERACOES ESPECIAIS: TRANSFERENCIAS CON... 0EC2 - TRANSFERENCIAS ESPECIAIS TRANSFERENCIAS ESPECIAIS 202237170006 100.000,00 0,00 0,00 100.000,00 0,00 100.000,00 NaN
1 2024 Emenda Individual - Transferências Especiais JUNIO AMARAL 16 MINAS GERAIS (UF) Encargos especiais Outras transferências 0903 - OPERACOES ESPECIAIS: TRANSFERENCIAS CON... 0EC2 - TRANSFERENCIAS ESPECIAIS TRANSFERENCIAS ESPECIAIS 202439240016 100.000,00 0,00 0,00 0,00 0,00 0,00 NaN
2 2024 Emenda Individual - Transferências Especiais JOAQUIM PASSARINHO 14 PARÁ (UF) Encargos especiais Outras transferências 0903 - OPERACOES ESPECIAIS: TRANSFERENCIAS CON... 0EC2 - TRANSFERENCIAS ESPECIAIS TRANSFERENCIAS ESPECIAIS 202436920014 100.000,00 100.000,00 100.000,00 0,00 0,00 0,00 NaN
3 2022 Emenda Individual - Transferências Especiais VINICIUS FARAH 23 PATY DO ALFERES - RJ Encargos especiais Outras transferências 0903 - OPERACOES ESPECIAIS: TRANSFERENCIAS CON... 0EC2 - TRANSFERENCIAS ESPECIAIS TRANSFERENCIAS ESPECIAIS 202240750023 100.000,00 0,00 0,00 100.000,00 0,00 100.000,00 NaN
4 2023 Emenda Individual - Transferências Especiais SERGIO PETECAO 8 Nacional Encargos especiais Outras transferências 0903 - OPERACOES ESPECIAIS: TRANSFERENCIAS CON... 0EC2 - TRANSFERENCIAS ESPECIAIS TRANSFERENCIAS ESPECIAIS 202329140008 100.000,00 100.000,00 100.000,00 0,00 0,00 0,00 NaN

Selecionando colunas#

Selecionamos apenas as colunas de nosso interesse.

df = df[['emenda_autor', 'local_gasto','vlr_empenhado','vlr_liquido','vlr_pago','vlr_restos_pagar_inscrito','vlr_restos_pagar_cancelados','vlr_restos_pagar_pagos']]
# print(type(df['vlr_empenhado'][0]))
df.head()
emenda_autor local_gasto vlr_empenhado vlr_liquido vlr_pago vlr_restos_pagar_inscrito vlr_restos_pagar_cancelados vlr_restos_pagar_pagos
0 MARCIO ALVINO SÃO PAULO (UF) 100.000,00 0,00 0,00 100.000,00 0,00 100.000,00
1 JUNIO AMARAL MINAS GERAIS (UF) 100.000,00 0,00 0,00 0,00 0,00 0,00
2 JOAQUIM PASSARINHO PARÁ (UF) 100.000,00 100.000,00 100.000,00 0,00 0,00 0,00
3 VINICIUS FARAH PATY DO ALFERES - RJ 100.000,00 0,00 0,00 100.000,00 0,00 100.000,00
4 SERGIO PETECAO Nacional 100.000,00 100.000,00 100.000,00 0,00 0,00 0,00

Convertendo valores#

As colunas de valores hoje estão como tipo de dado str. Precisam ser convertidas para float. Para isso vou subtituir o separador . por nada, e depois o separador

Podemos fazer coluna por coluna. Por exemplo:

df['vlr_empenhado'] = df['vlr_empenhado'].apply(lambda x: float(x.replace(".","").replace(",",".")))

Ou, como as colunas com valores começam com vlr_, podemos aplicar uma função nas colunas que iniciam com este prefixo.

# def ajustar_valores(df):
#     df['vlr_empenhado'] = df['vlr_empenhado'].apply(lambda x: float(x.replace(".","").replace(",",".")))

#     df['vlr_liquido'] = df['vlr_liquido'].apply(lambda x: float(x.replace(".","").replace(",",".")))

#     df['vlr_pago'] = df['vlr_pago'].apply(lambda x: float(x.replace(".","").replace(",",".")))

#     df['vlr_restos_pagar_inscrito'] = df['vlr_restos_pagar_inscrito'].apply(lambda x: float(x.replace(".","").replace(",",".")))

#     df['vlr_restos_pagar_cancelados'] = df['vlr_restos_pagar_cancelados'].apply(lambda x: float(x.replace(".","").replace(",",".")))

#     df['vlr_restos_pagar_pagos'] = df['vlr_restos_pagar_pagos'].apply(lambda x: float(x.replace(".","").replace(",",".")))
#     return df

# df = ajustar_valores(df)
# df.info()
def convert_to_float(x):
    return float(x.replace(".","").replace(",","."))

prefix = 'vlr_'
# df2 = df.loc[:, df.columns.str.startswith(prefix)] = df.loc[:, df.columns.str.startswith(prefix)].apply(convert_to_float)
colunas = [col for col in df if col.startswith(prefix)]
for coluna in colunas:
    df[coluna] = df[coluna].map(lambda x: convert_to_float(x))

df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 2849 entries, 0 to 2848
Data columns (total 8 columns):
 #   Column                       Non-Null Count  Dtype  
---  ------                       --------------  -----  
 0   emenda_autor                 2849 non-null   object 
 1   local_gasto                  2849 non-null   object 
 2   vlr_empenhado                2849 non-null   float64
 3   vlr_liquido                  2849 non-null   float64
 4   vlr_pago                     2849 non-null   float64
 5   vlr_restos_pagar_inscrito    2849 non-null   float64
 6   vlr_restos_pagar_cancelados  2849 non-null   float64
 7   vlr_restos_pagar_pagos       2849 non-null   float64
dtypes: float64(6), object(2)
memory usage: 178.2+ KB

Ajustando valor pago#

A emenda pode ter sido paga, então vlr_pago > 0; pode ter ido para restos a pagar, então vlr_restos_pagar_pagos > 0, ou ainda não ter sido paga. Estamos interessados nas que foram pagas (vlr_pago > 0 ou vlr_restos_pagar_pagos > 0).

# Criar nova coluna, caso a nova coluna for maior que zero
# significa que aquela emanda foi paga
df['vlr'] = df['vlr_pago']+df['vlr_restos_pagar_pagos']
df = df[df['vlr']>0]

# selecionar apenas colunas de interesse
df = df[['emenda_autor','local_gasto','vlr']]
df.head()
emenda_autor local_gasto vlr
0 MARCIO ALVINO SÃO PAULO (UF) 100000.0
2 JOAQUIM PASSARINHO PARÁ (UF) 100000.0
3 VINICIUS FARAH PATY DO ALFERES - RJ 100000.0
4 SERGIO PETECAO Nacional 100000.0
6 EDILAZIO JUNIOR CODÓ - MA 100000.0

Emendas#

Emendas Estaduais#

Filtrar apenas as emendas enviadas para estados.

Quero a informação de qual o volume financeiro recebido e quantos políticos envolvidos.

# Emendas enviadas por estados terminam com (UF)
emendas_estaduais = df.loc[df['local_gasto'].str.contains('(UF)',regex=False), ['local_gasto', 'vlr','emenda_autor']]

# quanto foi enviado
emendas_estaduais = (emendas_estaduais.groupby('local_gasto').agg({'local_gasto':'count', 'vlr': 'sum', 'emenda_autor':pd.Series.nunique})
                    .rename(columns={'local_gasto':'Emendas', 'emenda_autor':'Políticos'})
                    .reset_index())

# retirando a marcação (UF) do nome do estado.
emendas_estaduais["local_gasto"] = emendas_estaduais["local_gasto"].apply(lambda x: x.replace(" (UF)", ""))

# renomeando a coluna local_gasto
emendas_estaduais.rename(columns={'local_gasto':'Estado'}, inplace=True)

# formatando o valor
emendas_estaduais["Valor"] = emendas_estaduais["vlr"].apply(lambda x: format_currency(x, currency="BRL", locale="pt_BR"))

emendas_estaduais[['Estado','Políticos','Emendas','Valor']]
Estado Políticos Emendas Valor
0 ACRE 19 59 R$ 270.668.887,72
1 ALAGOAS 16 27 R$ 288.547.617,91
2 AMAPÁ 18 45 R$ 350.701.642,85
3 AMAZONAS 12 34 R$ 242.881.420,64
4 BAHIA 52 148 R$ 1.075.305.291,73
5 CEARÁ 28 61 R$ 476.996.674,15
6 DISTRITO FEDERAL 4 5 R$ 28.724.356,38
7 ESPÍRITO SANTO 17 33 R$ 208.546.895,42
8 GOIÁS 28 63 R$ 449.253.444,39
9 MARANHÃO 32 73 R$ 642.742.781,03
10 MATO GROSSO 15 26 R$ 250.405.540,72
11 MATO GROSSO DO SUL 15 46 R$ 274.989.432,62
12 MINAS GERAIS 69 179 R$ 1.280.384.685,02
13 PARANÁ 41 110 R$ 765.282.505,91
14 PARAÍBA 20 71 R$ 441.416.282,17
15 PARÁ 28 73 R$ 529.455.591,48
16 PERNAMBUCO 38 81 R$ 621.529.087,67
17 PIAUÍ 20 47 R$ 460.788.039,12
18 RIO DE JANEIRO 44 82 R$ 274.456.608,74
19 RIO GRANDE DO NORTE 16 46 R$ 325.306.366,19
20 RIO GRANDE DO SUL 41 92 R$ 864.090.040,19
21 RONDÔNIA 17 31 R$ 378.531.271,66
22 RORAIMA 16 42 R$ 299.764.800,42
23 SANTA CATARINA 26 51 R$ 443.845.664,20
24 SERGIPE 17 42 R$ 356.215.023,04
25 SÃO PAULO 79 172 R$ 1.120.947.911,35
26 TOCANTINS 18 33 R$ 321.699.311,86

Vamos criar um treemap para ver melhor os dados.

# apresentar os valores no formato 1K, 1M, 1B
def f(row):
    if row['vlr'] >= 10**9:
        val = row['vlr']/10**9
        val = '{0:.2f}B'.format(val)
    elif row['vlr'] >= 10**6 and row['vlr'] < 10**9:
        val = row['vlr']/10**6
        val = '{0:.2f}M'.format(val)
    elif row['vlr'] >= 10**3 and row['vlr'] < 10**6:
        val = row['vlr']/10**3
        val = '{0:.2f}K'.format(val)
    else:
        val = '{0:.2f}'.format(row['vlr'])
    return val

emendas_estaduais['vlr_prty'] = emendas_estaduais.apply(f, axis=1)

# treemap com os valores por estado
fig1 = px.treemap(emendas_estaduais, path=[px.Constant("Brasil"), "Estado"], values="vlr", color="vlr", color_continuous_scale='viridis')
fig1.update_traces(
text=emendas_estaduais['vlr_prty'],
textinfo="label+text+percent root", root_color="lightgrey", selector=dict(type='treemap')
, name="asdasdasd", opacity=0.75
)
fig1.show()

Emendas Ceará#

  • quais políticos enviaram emendas

# Dados do estado do ceará e das cidades do ceará
def separar_dados_ce(df):
    # emenda direto pro estado do Ceará
    df_estado = df.loc[df['local_gasto']=='CEARÁ (UF)']

    # emendas para as cidade tem a marcação "- CE"
    df_cidades = df.loc[df['local_gasto'].str.contains('- CE')]

    # limpando o nome das cidades, retirando a marcação "- CE"
    # df_cidades['local_gasto'] = df_cidades["local_gasto"].apply(lambda x: x.replace(" - CE", ""))
    
    # df_ce = pd.concat([df_estados, df_cidades], axis=0)
    # df_ce = df_ce[['emenda_autor', 'local_gasto','vlr','vlr_empenhado','vlr_liquido','vlr_pago','vlr_restos_pagar_inscrito','vlr_restos_pagar_cancelados','vlr_restos_pagar_pagos']]
    # df_ce = pd.DataFrame(df_ce).sort_values(by=['vlr'], ascending=False)
    # return df_ce
    return df_estado.reset_index(drop=True), df_cidades.reset_index(drop=True)

df_ce, df_cidades = separar_dados_ce(df)
# df_cidades.head()

# limpando o nome das cidades
df_cidades['local_gasto'] = df_cidades["local_gasto"].apply(lambda x: x.replace(" - CE", ""))
df_cidades.head()
emenda_autor local_gasto vlr
0 ROBERIO MONTEIRO MORADA NOVA 100000.0
1 CID GOMES COREAÚ 250000.0
2 CID GOMES ALCÂNTARAS 250000.0
3 ROBERIO MONTEIRO BELA CRUZ 400000.0
4 PEDRO AUGUSTO BEZERRA PARACURU 500000.0

Cidades Recebedoras#

Cidades que receberam emendas. Filtrando apenas cidades que já receberam.

def cidades_emendas(df_ce):
    locais = sorted(df_ce['local_gasto'].unique())
    locais = pd.DataFrame({'cidade':locais})
    return locais


def espalhar_cidades(series):
    # Create a pandas Series
    # Number of columns
    n = 5

    # Calculate the number of rows needed
    num_rows = int(np.ceil(len(series) / n))

    # Pad the Series with NaN values if necessary
    padded_series = np.pad(series, (0, num_rows * n - len(series)), constant_values='')

    # Reshape the Series and convert it to a DataFrame
    reshaped_array = padded_series.reshape(num_rows, n)
    return pd.DataFrame(reshaped_array)


locais = cidades_emendas(df_cidades)

#limpando o nome das cidades
# locais['cidade'] = locais["cidade"].apply(lambda x: x.replace(" - CE", ""))
locais


# quero espalhar esta lista num dataframe para visualizar melhor
df_locais = espalhar_cidades(locais['cidade'])
df_locais
0 1 2 3 4
0 ACARAÚ ALCÂNTARAS ALTANEIRA AMONTADA AQUIRAZ
1 ARATUBA ASSARÉ BELA CRUZ BOA VIAGEM CARIRIAÇU
2 CARIRÉ CHAVAL CHOROZINHO CHORÓ COREAÚ
3 CRUZ FORTIM FRECHEIRINHA GRANJA IBIAPINA
4 IBICUITINGA ICÓ IPU IRACEMA ITAPIPOCA
5 ITAREMA JAGUARIBARA JAGUARIBE MARANGUAPE MILHÃ
6 MONSENHOR TABOSA MORADA NOVA MORAÚJO MUCAMBO NOVA RUSSAS
7 NOVO ORIENTE PARACURU PARAIPABA PARAMBU PEDRA BRANCA
8 PENTECOSTE PIRES FERREIRA QUITERIANÓPOLIS RERIUTABA RUSSAS
9 SENADOR POMPEU SÃO BENEDITO TAMBORIL URUOCA

Cidade e valor recebido#

Quanto cada cidade recebeu e de quantos políticos diferentes.

def f(row):
    if row['vlr'] >= 10**9:
        val = row['vlr']/10**9
        val = '{0:.2f}B'.format(val)
    elif row['vlr'] >= 10**6 and row['vlr'] < 10**9:
        val = row['vlr']/10**6
        val = '{0:.2f}M'.format(val)
    elif row['vlr'] >= 10**3 and row['vlr'] < 10**6:
        val = row['vlr']/10**3
        val = '{0:.2f}K'.format(val)
    else:
        val = '{0:.2f}'.format(row['vlr'])
    return val


cidades_emendas_df = (df_cidades.groupby('local_gasto', as_index=False).agg({'emenda_autor':pd.Series.nunique, 'vlr': 'sum'})
                    .reset_index(drop=True))
# )


cidades_emendas_df.rename(columns={'local_gasto':'Cidade', 'emenda_autor':'Políticos'}, inplace=True)
# cidades_emendas_df['local_gasto'] = cidades_emendas_df["local_gasto"].apply(lambda x: x.replace(" - CE", ""))
# cidades_emendas_df = cidades_emendas_df.sort_values(by='vlr', ascending=False)
# cidades_emendas_df.info()
# cidades_emendas_df


cidades_emendas_df["Valor (R$)"] = cidades_emendas_df["vlr"].apply(lambda x: format_currency(x, currency="BRL", locale="pt_BR"))
cidades_emendas_df['vlr_prty'] = cidades_emendas_df.apply(f, axis=1)
# cidades_emendas_df#.head()#[['Cidade','Políticos','Valor']]
cidades_emendas_df.head()
Cidade Políticos vlr Valor (R$) vlr_prty
0 ACARAÚ 1 2724347.87 R$ 2.724.347,87 2.72M
1 ALCÂNTARAS 1 250000.00 R$ 250.000,00 250.00K
2 ALTANEIRA 1 1000012.00 R$ 1.000.012,00 1.00M
3 AMONTADA 1 1000000.00 R$ 1.000.000,00 1.00M
4 AQUIRAZ 2 4672458.52 R$ 4.672.458,52 4.67M

Criando um treemap para ver melhor.

# fig1 = px.treemap(cidades_emendas_df, path=["Cidade"], values="vlr",color="vlr",color_continuous_scale='viridis')
# fig1.update_traces(
#     #textinfo="label+value"
#     texttemplate='%{label} <br> %{value: text} <br> %{percentRoot}'
#     ,selector=dict(type='treemap')
# )
# fig1.show()




# emendas_estaduais[['Estado','Políticos','Emendas','vlr_prty', 'Valor']]
# cidades_emendas_df.head()

fig2 = px.treemap(cidades_emendas_df, path=[px.Constant("Cidades do Ceará"),"Cidade"], values="vlr", color="vlr", color_continuous_scale='viridis')
fig2.update_traces(
    text=cidades_emendas_df['vlr_prty'],
    textinfo="label+text", 
    selector=dict(type='treemap'), 
    opacity=0.75
)
fig2.show()

Outliers#

Dados no formato de boxplot. Não agregado para poder verificar outliers.

fig = px.box(df_cidades, x="vlr")
fig.show()

Verificando os outliers. Identificando os outliers.

def identificar_limites(serie_coluna):
    # Calcular os quartis Q1 e Q3
    Q1 = serie_coluna.quantile(0.25)
    Q3 = serie_coluna.quantile(0.75)

    # Calcular o IQR
    IQR = Q3 - Q1

    # Definir os limites inferior e superior
    limite_inferior = Q1 - 1.5 * IQR
    limite_superior = Q3 + 1.5 * IQR
    return limite_inferior, limite_superior

def get_outliers(df,coluna):
    limite_inferior,limite_superior = identificar_limites(df[coluna])
    outliers = df[(df[coluna] < limite_inferior) | (df[coluna] > limite_superior)]
    return outliers.sort_values(by='vlr', ascending=False)
    # return outliers


def get_noutliers(df,coluna):
    limite_inferior,limite_superior = identificar_limites(df[coluna])
    outliers = df[~((df[coluna] < limite_inferior) | (df[coluna] > limite_superior))]
    return outliers.sort_values(by='vlr', ascending=False)
    # return outliers


# Identificar outliers
outliers = get_outliers(df_cidades,'vlr')

outliers = outliers[['emenda_autor','local_gasto','vlr']]
outliers = outliers.rename(columns={'emenda_autor':'Político','local_gasto':'Cidade'})

outliers["Valor"] = outliers["vlr"].apply(lambda x: format_currency(x, currency="BRL", locale="pt_BR"))
outliers[['Político','Cidade','Valor']]
Político Cidade Valor
75 MOSES RODRIGUES CRUZ R$ 10.000.000,00
74 HEITOR FREIRE GRANJA R$ 7.331.441,00
73 YURY DO PAREDAO QUITERIANÓPOLIS R$ 7.000.000,00
72 PEDRO AUGUSTO BEZERRA NOVO ORIENTE R$ 6.000.000,00
71 GENECIAS NORONHA PARAMBU R$ 5.819.682,00
70 DR. JAZIEL NOVO ORIENTE R$ 5.702.232,00
# nao outliers
noutliers = get_noutliers(df_cidades,'vlr')
noutliers.head()
emenda_autor local_gasto vlr
68 JOSE AIRTON FELIX CIRILO NOVO ORIENTE 5000000.0
67 DENIS BEZERRA IPU 4947710.0
65 DR. JAZIEL BOA VIAGEM 4887627.0
66 VAIDON OLIVEIRA IPU 4887627.0
64 VAIDON OLIVEIRA PENTECOSTE 4073023.0

Políticos#

  • politicos que enviaram

  • políticos enviaram para quantas cidades diferentes

  • valor enviado por cada político

politicos_df = (
    df_cidades
    .groupby(['emenda_autor'], as_index=False)
    .agg({'local_gasto':pd.Series.nunique, 'vlr': 'sum'})
)


# politicos_df = politicos_df.sort_values(by='vlr', ascending=False)
politicos_df.rename(columns={'emenda_autor':'Autor', 'local_gasto':'Cidades Recebedoras','vlr':'Valor'}, inplace=True)



politicos_df.style \
.set_caption("Emendas por Político") \
.format(precision=2, thousands=".", decimal=",") \
.background_gradient(subset=["Valor"],cmap="viridis") \
.highlight_max(subset=["Cidades Recebedoras"], color='yellow', axis=0, props=None)
---------------------------------------------------------------------------
ImportError                               Traceback (most recent call last)
File ~/.cache/pypoetry/virtualenvs/emendas-teste-Jhf3VwlE-py3.12/lib/python3.12/site-packages/IPython/core/formatters.py:347, in BaseFormatter.__call__(self, obj)
    345     method = get_real_method(obj, self.print_method)
    346     if method is not None:
--> 347         return method()
    348     return None
    349 else:

File ~/.cache/pypoetry/virtualenvs/emendas-teste-Jhf3VwlE-py3.12/lib/python3.12/site-packages/pandas/io/formats/style.py:405, in Styler._repr_html_(self)
    400 """
    401 Hooks into Jupyter notebook rich display system, which calls _repr_html_ by
    402 default if an object is returned at the end of a cell.
    403 """
    404 if get_option("styler.render.repr") == "html":
--> 405     return self.to_html()
    406 return None

File ~/.cache/pypoetry/virtualenvs/emendas-teste-Jhf3VwlE-py3.12/lib/python3.12/site-packages/pandas/io/formats/style.py:1345, in Styler.to_html(self, buf, table_uuid, table_attributes, sparse_index, sparse_columns, bold_headers, caption, max_rows, max_columns, encoding, doctype_html, exclude_styles, **kwargs)
   1342     obj.set_caption(caption)
   1344 # Build HTML string..
-> 1345 html = obj._render_html(
   1346     sparse_index=sparse_index,
   1347     sparse_columns=sparse_columns,
   1348     max_rows=max_rows,
   1349     max_cols=max_columns,
   1350     exclude_styles=exclude_styles,
   1351     encoding=encoding or get_option("styler.render.encoding"),
   1352     doctype_html=doctype_html,
   1353     **kwargs,
   1354 )
   1356 return save_to_buffer(
   1357     html, buf=buf, encoding=(encoding if buf is not None else None)
   1358 )

File ~/.cache/pypoetry/virtualenvs/emendas-teste-Jhf3VwlE-py3.12/lib/python3.12/site-packages/pandas/io/formats/style_render.py:204, in StylerRenderer._render_html(self, sparse_index, sparse_columns, max_rows, max_cols, **kwargs)
    192 def _render_html(
    193     self,
    194     sparse_index: bool,
   (...)
    198     **kwargs,
    199 ) -> str:
    200     """
    201     Renders the ``Styler`` including all applied styles to HTML.
    202     Generates a dict with necessary kwargs passed to jinja2 template.
    203     """
--> 204     d = self._render(sparse_index, sparse_columns, max_rows, max_cols, "&nbsp;")
    205     d.update(kwargs)
    206     return self.template_html.render(
    207         **d,
    208         html_table_tpl=self.template_html_table,
    209         html_style_tpl=self.template_html_style,
    210     )

File ~/.cache/pypoetry/virtualenvs/emendas-teste-Jhf3VwlE-py3.12/lib/python3.12/site-packages/pandas/io/formats/style_render.py:161, in StylerRenderer._render(self, sparse_index, sparse_columns, max_rows, max_cols, blank)
    147 def _render(
    148     self,
    149     sparse_index: bool,
   (...)
    153     blank: str = "",
    154 ):
    155     """
    156     Computes and applies styles and then generates the general render dicts.
    157 
    158     Also extends the `ctx` and `ctx_index` attributes with those of concatenated
    159     stylers for use within `_translate_latex`
    160     """
--> 161     self._compute()
    162     dxs = []
    163     ctx_len = len(self.index)

File ~/.cache/pypoetry/virtualenvs/emendas-teste-Jhf3VwlE-py3.12/lib/python3.12/site-packages/pandas/io/formats/style_render.py:256, in StylerRenderer._compute(self)
    254 r = self
    255 for func, args, kwargs in self._todo:
--> 256     r = func(self)(*args, **kwargs)
    257 return r

File ~/.cache/pypoetry/virtualenvs/emendas-teste-Jhf3VwlE-py3.12/lib/python3.12/site-packages/pandas/io/formats/style.py:1726, in Styler._apply(self, func, axis, subset, **kwargs)
   1724 axis = self.data._get_axis_number(axis)
   1725 if axis == 0:
-> 1726     result = data.apply(func, axis=0, **kwargs)
   1727 else:
   1728     result = data.T.apply(func, axis=0, **kwargs).T  # see GH 42005

File ~/.cache/pypoetry/virtualenvs/emendas-teste-Jhf3VwlE-py3.12/lib/python3.12/site-packages/pandas/core/frame.py:10374, in DataFrame.apply(self, func, axis, raw, result_type, args, by_row, engine, engine_kwargs, **kwargs)
  10360 from pandas.core.apply import frame_apply
  10362 op = frame_apply(
  10363     self,
  10364     func=func,
   (...)
  10372     kwargs=kwargs,
  10373 )
> 10374 return op.apply().__finalize__(self, method="apply")

File ~/.cache/pypoetry/virtualenvs/emendas-teste-Jhf3VwlE-py3.12/lib/python3.12/site-packages/pandas/core/apply.py:916, in FrameApply.apply(self)
    913 elif self.raw:
    914     return self.apply_raw(engine=self.engine, engine_kwargs=self.engine_kwargs)
--> 916 return self.apply_standard()

File ~/.cache/pypoetry/virtualenvs/emendas-teste-Jhf3VwlE-py3.12/lib/python3.12/site-packages/pandas/core/apply.py:1063, in FrameApply.apply_standard(self)
   1061 def apply_standard(self):
   1062     if self.engine == "python":
-> 1063         results, res_index = self.apply_series_generator()
   1064     else:
   1065         results, res_index = self.apply_series_numba()

File ~/.cache/pypoetry/virtualenvs/emendas-teste-Jhf3VwlE-py3.12/lib/python3.12/site-packages/pandas/core/apply.py:1081, in FrameApply.apply_series_generator(self)
   1078 with option_context("mode.chained_assignment", None):
   1079     for i, v in enumerate(series_gen):
   1080         # ignore SettingWithCopy here in case the user mutates
-> 1081         results[i] = self.func(v, *self.args, **self.kwargs)
   1082         if isinstance(results[i], ABCSeries):
   1083             # If we have a view on v, we need to make a copy because
   1084             #  series_generator will swap out the underlying data
   1085             results[i] = results[i].copy(deep=False)

File ~/.cache/pypoetry/virtualenvs/emendas-teste-Jhf3VwlE-py3.12/lib/python3.12/site-packages/pandas/io/formats/style.py:3806, in _background_gradient(data, cmap, low, high, text_color_threshold, vmin, vmax, gmap, text_only)
   3803 else:  # else validate gmap against the underlying data
   3804     gmap = _validate_apply_axis_arg(gmap, "gmap", float, data)
-> 3806 with _mpl(Styler.background_gradient) as (_, _matplotlib):
   3807     smin = np.nanmin(gmap) if vmin is None else vmin
   3808     smax = np.nanmax(gmap) if vmax is None else vmax

File /usr/local/python/3.12.1/lib/python3.12/contextlib.py:137, in _GeneratorContextManager.__enter__(self)
    135 del self.args, self.kwds, self.func
    136 try:
--> 137     return next(self.gen)
    138 except StopIteration:
    139     raise RuntimeError("generator didn't yield") from None

File ~/.cache/pypoetry/virtualenvs/emendas-teste-Jhf3VwlE-py3.12/lib/python3.12/site-packages/pandas/io/formats/style.py:98, in _mpl(func)
     96     yield plt, mpl
     97 else:
---> 98     raise ImportError(f"{func.__name__} requires matplotlib.")

ImportError: background_gradient requires matplotlib.
<pandas.io.formats.style.Styler at 0x795e067a9c70>
variaval1 = 10
variavel2 = 20

Primeiro valor e segundo valor